package org.beehoo.web.framework.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.beehoo.web.framework.util.StringUtil;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;


public abstract class BaseDAO {

	@Autowired
	private HibernateTemplate hibernateTemplate;

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public <T extends IdEntity> T get(Class<T> clazz, Serializable id) {
		return hibernateTemplate.get(clazz, id);
	}

	public void delete(Class clazz, Serializable id) {
		Object entity = hibernateTemplate.get(clazz, id);
		hibernateTemplate.delete(entity);
	}

	public void save(IdEntity entity) {
		hibernateTemplate.save(entity);
	}

	public void update(IdEntity entity) {
		hibernateTemplate.update(entity);
	}

	public void saveOrUpdate(IdEntity entity) {
		hibernateTemplate.saveOrUpdate(entity);
	}

	private long count(String ql, final Map<String, Object> values) {
		String fromHql = ql;
		// select子句与order by子句会影响count查询,进行简单的排除.
		fromHql = "from " + StringUtil.substringAfter(fromHql, "from");
		fromHql = StringUtil.substringBefore(fromHql, "order by");

		final String countHql = "select count(*) " + fromHql;
		Long count = hibernateTemplate.execute(new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(countHql);
				if (values != null) {
					query.setProperties(values);
				}
				return query.uniqueResult();
			}

		});
		return count.longValue();
	}

	public <X> List<X> findPage(final Page page, final String hql, final Map<String, Object> values) {
		if (page.isAutoCount()) {
			page.setTotal(count(hql, values));
		}
		return hibernateTemplate.execute(new HibernateCallback<List<X>>() {
			@SuppressWarnings( { "unchecked", "synthetic-access" })
			public List<X> doInHibernate(Session session) throws HibernateException {
				Query query = session.createQuery(hql);
				if (values != null) {
					query.setProperties(values);
				}
				query.setFirstResult(page.getFirst());
				query.setMaxResults(page.getPageSize());
				//
				return query.list();
			}
		});
	}
	
	public <X> List<X> find(final String hql, final Object...values){
		return hibernateTemplate.find(hql, values);
	}
	
}
